convert the X coordinates so they're with respect to the line, rather than
authorHavoc Pennington <hp@redhat.com>
Sat, 17 Feb 2001 00:11:03 +0000 (00:11 +0000)
committerHavoc Pennington <hp@src.gnome.org>
Sat, 17 Feb 2001 00:11:03 +0000 (00:11 +0000)
2001-02-15  Havoc Pennington  <hp@redhat.com>

* gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): convert
the X coordinates so they're with respect to the line, rather than
with respect to the layout.

* gtk/gtkalignment.c: Convert to new property API, patch from Lee
Mallabone

* gtk/testgtk.c (create_range_controls): add vscale tests,
and inverted test

* gtk/gtkrange.c (gtk_range_set_inverted): new function to fix
#50806

* gtk/gtkentry.c (gtk_entry_get_text): add G_CONST_RETURN

* gtk/gtktextiter.h (gtk_text_iter_is_last): rename
gtk_text_iter_is_end

* gtk/gtktextbuffer.h (gtk_text_buffer_get_last_iter):
rename gtk_text_buffer_get_end_iter

* gtk/testgtk.c (create_labels): Add test for selectable

* gtk/gtkentry.c (gtk_entry_draw_text): Use new GDK API to draw
the selection stuff. This code is kind of broken since it doesn't
use the theme engine.

* gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region):
fix infinite loop and y offset problem
(gdk_draw_layout_line_with_colors): fix foreground color handling

        * gtk/gtklabel.h, gtk/gtklabel.c: Implement a "selectable" flag
that makes the label selectable.

* gtk/gtklabel.c (gtk_label_style_set): recreate the label's
layout when the style is set, since fonts etc. could have changed.

29 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gdk/gdkpango.c
gtk/gtkalignment.c
gtk/gtkentry.c
gtk/gtkentry.h
gtk/gtklabel.c
gtk/gtklabel.h
gtk/gtkrange.c
gtk/gtkrange.h
gtk/gtktextbtree.c
gtk/gtktextbtree.h
gtk/gtktextbuffer.c
gtk/gtktextbuffer.h
gtk/gtktextiter.c
gtk/gtktextiter.h
gtk/gtktextlayout.c
gtk/gtktextview.c
gtk/testgtk.c
gtk/testtext.c
gtk/testtextbuffer.c
tests/testgtk.c
tests/testtext.c
tests/testtextbuffer.c

index 5a0cdd22cd8d80b5eab35459152efd243a09478f..b495a1029c5f472f1b7e50643288a91504cabfa8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,46 @@
+2001-02-15  Havoc Pennington  <hp@redhat.com>
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): convert
+       the X coordinates so they're with respect to the line, rather than 
+       with respect to the layout.
+
+       * gtk/gtkalignment.c: Convert to new property API, patch from Lee
+       Mallabone
+
+       * gtk/testgtk.c (create_range_controls): add vscale tests, 
+       and inverted test
+
+       * gtk/gtkrange.c (gtk_range_set_inverted): new function to fix 
+       #50806
+
+       * gtk/gtkentry.c (gtk_entry_get_text): add G_CONST_RETURN
+
+       * gtk/gtktextiter.h (gtk_text_iter_is_last): rename 
+       gtk_text_iter_is_end
+
+       * gtk/gtktextbuffer.h (gtk_text_buffer_get_last_iter):
+       rename gtk_text_buffer_get_end_iter
+
+       * gtk/testgtk.c (create_labels): Add test for selectable
+
+       * gtk/gtkentry.c (gtk_entry_draw_text): Use new GDK API to draw
+       the selection stuff. This code is kind of broken since it doesn't 
+       use the theme engine.
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): 
+       fix infinite loop and y offset problem
+       (gdk_draw_layout_line_with_colors): fix foreground color handling
+
+        * gtk/gtklabel.h, gtk/gtklabel.c: Implement a "selectable" flag 
+       that makes the label selectable.
+       
+       * gtk/gtklabel.c (gtk_label_style_set): recreate the label's
+       layout when the style is set, since fonts etc. could have changed.      
+
 Fri Feb 16 14:22:05 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/Makefile.am: Removed gtktreemodelsimple.[ch]
+
        * gtk/gtktreemodelsimple.[ch]: removes
 
 2001-02-16  Alexander Larsson  <alexl@redhat.com>
index 5a0cdd22cd8d80b5eab35459152efd243a09478f..b495a1029c5f472f1b7e50643288a91504cabfa8 100644 (file)
@@ -1,6 +1,46 @@
+2001-02-15  Havoc Pennington  <hp@redhat.com>
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): convert
+       the X coordinates so they're with respect to the line, rather than 
+       with respect to the layout.
+
+       * gtk/gtkalignment.c: Convert to new property API, patch from Lee
+       Mallabone
+
+       * gtk/testgtk.c (create_range_controls): add vscale tests, 
+       and inverted test
+
+       * gtk/gtkrange.c (gtk_range_set_inverted): new function to fix 
+       #50806
+
+       * gtk/gtkentry.c (gtk_entry_get_text): add G_CONST_RETURN
+
+       * gtk/gtktextiter.h (gtk_text_iter_is_last): rename 
+       gtk_text_iter_is_end
+
+       * gtk/gtktextbuffer.h (gtk_text_buffer_get_last_iter):
+       rename gtk_text_buffer_get_end_iter
+
+       * gtk/testgtk.c (create_labels): Add test for selectable
+
+       * gtk/gtkentry.c (gtk_entry_draw_text): Use new GDK API to draw
+       the selection stuff. This code is kind of broken since it doesn't 
+       use the theme engine.
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): 
+       fix infinite loop and y offset problem
+       (gdk_draw_layout_line_with_colors): fix foreground color handling
+
+        * gtk/gtklabel.h, gtk/gtklabel.c: Implement a "selectable" flag 
+       that makes the label selectable.
+       
+       * gtk/gtklabel.c (gtk_label_style_set): recreate the label's
+       layout when the style is set, since fonts etc. could have changed.      
+
 Fri Feb 16 14:22:05 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/Makefile.am: Removed gtktreemodelsimple.[ch]
+
        * gtk/gtktreemodelsimple.[ch]: removes
 
 2001-02-16  Alexander Larsson  <alexl@redhat.com>
index 5a0cdd22cd8d80b5eab35459152efd243a09478f..b495a1029c5f472f1b7e50643288a91504cabfa8 100644 (file)
@@ -1,6 +1,46 @@
+2001-02-15  Havoc Pennington  <hp@redhat.com>
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): convert
+       the X coordinates so they're with respect to the line, rather than 
+       with respect to the layout.
+
+       * gtk/gtkalignment.c: Convert to new property API, patch from Lee
+       Mallabone
+
+       * gtk/testgtk.c (create_range_controls): add vscale tests, 
+       and inverted test
+
+       * gtk/gtkrange.c (gtk_range_set_inverted): new function to fix 
+       #50806
+
+       * gtk/gtkentry.c (gtk_entry_get_text): add G_CONST_RETURN
+
+       * gtk/gtktextiter.h (gtk_text_iter_is_last): rename 
+       gtk_text_iter_is_end
+
+       * gtk/gtktextbuffer.h (gtk_text_buffer_get_last_iter):
+       rename gtk_text_buffer_get_end_iter
+
+       * gtk/testgtk.c (create_labels): Add test for selectable
+
+       * gtk/gtkentry.c (gtk_entry_draw_text): Use new GDK API to draw
+       the selection stuff. This code is kind of broken since it doesn't 
+       use the theme engine.
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): 
+       fix infinite loop and y offset problem
+       (gdk_draw_layout_line_with_colors): fix foreground color handling
+
+        * gtk/gtklabel.h, gtk/gtklabel.c: Implement a "selectable" flag 
+       that makes the label selectable.
+       
+       * gtk/gtklabel.c (gtk_label_style_set): recreate the label's
+       layout when the style is set, since fonts etc. could have changed.      
+
 Fri Feb 16 14:22:05 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/Makefile.am: Removed gtktreemodelsimple.[ch]
+
        * gtk/gtktreemodelsimple.[ch]: removes
 
 2001-02-16  Alexander Larsson  <alexl@redhat.com>
index 5a0cdd22cd8d80b5eab35459152efd243a09478f..b495a1029c5f472f1b7e50643288a91504cabfa8 100644 (file)
@@ -1,6 +1,46 @@
+2001-02-15  Havoc Pennington  <hp@redhat.com>
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): convert
+       the X coordinates so they're with respect to the line, rather than 
+       with respect to the layout.
+
+       * gtk/gtkalignment.c: Convert to new property API, patch from Lee
+       Mallabone
+
+       * gtk/testgtk.c (create_range_controls): add vscale tests, 
+       and inverted test
+
+       * gtk/gtkrange.c (gtk_range_set_inverted): new function to fix 
+       #50806
+
+       * gtk/gtkentry.c (gtk_entry_get_text): add G_CONST_RETURN
+
+       * gtk/gtktextiter.h (gtk_text_iter_is_last): rename 
+       gtk_text_iter_is_end
+
+       * gtk/gtktextbuffer.h (gtk_text_buffer_get_last_iter):
+       rename gtk_text_buffer_get_end_iter
+
+       * gtk/testgtk.c (create_labels): Add test for selectable
+
+       * gtk/gtkentry.c (gtk_entry_draw_text): Use new GDK API to draw
+       the selection stuff. This code is kind of broken since it doesn't 
+       use the theme engine.
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): 
+       fix infinite loop and y offset problem
+       (gdk_draw_layout_line_with_colors): fix foreground color handling
+
+        * gtk/gtklabel.h, gtk/gtklabel.c: Implement a "selectable" flag 
+       that makes the label selectable.
+       
+       * gtk/gtklabel.c (gtk_label_style_set): recreate the label's
+       layout when the style is set, since fonts etc. could have changed.      
+
 Fri Feb 16 14:22:05 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/Makefile.am: Removed gtktreemodelsimple.[ch]
+
        * gtk/gtktreemodelsimple.[ch]: removes
 
 2001-02-16  Alexander Larsson  <alexl@redhat.com>
index 5a0cdd22cd8d80b5eab35459152efd243a09478f..b495a1029c5f472f1b7e50643288a91504cabfa8 100644 (file)
@@ -1,6 +1,46 @@
+2001-02-15  Havoc Pennington  <hp@redhat.com>
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): convert
+       the X coordinates so they're with respect to the line, rather than 
+       with respect to the layout.
+
+       * gtk/gtkalignment.c: Convert to new property API, patch from Lee
+       Mallabone
+
+       * gtk/testgtk.c (create_range_controls): add vscale tests, 
+       and inverted test
+
+       * gtk/gtkrange.c (gtk_range_set_inverted): new function to fix 
+       #50806
+
+       * gtk/gtkentry.c (gtk_entry_get_text): add G_CONST_RETURN
+
+       * gtk/gtktextiter.h (gtk_text_iter_is_last): rename 
+       gtk_text_iter_is_end
+
+       * gtk/gtktextbuffer.h (gtk_text_buffer_get_last_iter):
+       rename gtk_text_buffer_get_end_iter
+
+       * gtk/testgtk.c (create_labels): Add test for selectable
+
+       * gtk/gtkentry.c (gtk_entry_draw_text): Use new GDK API to draw
+       the selection stuff. This code is kind of broken since it doesn't 
+       use the theme engine.
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): 
+       fix infinite loop and y offset problem
+       (gdk_draw_layout_line_with_colors): fix foreground color handling
+
+        * gtk/gtklabel.h, gtk/gtklabel.c: Implement a "selectable" flag 
+       that makes the label selectable.
+       
+       * gtk/gtklabel.c (gtk_label_style_set): recreate the label's
+       layout when the style is set, since fonts etc. could have changed.      
+
 Fri Feb 16 14:22:05 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/Makefile.am: Removed gtktreemodelsimple.[ch]
+
        * gtk/gtktreemodelsimple.[ch]: removes
 
 2001-02-16  Alexander Larsson  <alexl@redhat.com>
index 5a0cdd22cd8d80b5eab35459152efd243a09478f..b495a1029c5f472f1b7e50643288a91504cabfa8 100644 (file)
@@ -1,6 +1,46 @@
+2001-02-15  Havoc Pennington  <hp@redhat.com>
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): convert
+       the X coordinates so they're with respect to the line, rather than 
+       with respect to the layout.
+
+       * gtk/gtkalignment.c: Convert to new property API, patch from Lee
+       Mallabone
+
+       * gtk/testgtk.c (create_range_controls): add vscale tests, 
+       and inverted test
+
+       * gtk/gtkrange.c (gtk_range_set_inverted): new function to fix 
+       #50806
+
+       * gtk/gtkentry.c (gtk_entry_get_text): add G_CONST_RETURN
+
+       * gtk/gtktextiter.h (gtk_text_iter_is_last): rename 
+       gtk_text_iter_is_end
+
+       * gtk/gtktextbuffer.h (gtk_text_buffer_get_last_iter):
+       rename gtk_text_buffer_get_end_iter
+
+       * gtk/testgtk.c (create_labels): Add test for selectable
+
+       * gtk/gtkentry.c (gtk_entry_draw_text): Use new GDK API to draw
+       the selection stuff. This code is kind of broken since it doesn't 
+       use the theme engine.
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): 
+       fix infinite loop and y offset problem
+       (gdk_draw_layout_line_with_colors): fix foreground color handling
+
+        * gtk/gtklabel.h, gtk/gtklabel.c: Implement a "selectable" flag 
+       that makes the label selectable.
+       
+       * gtk/gtklabel.c (gtk_label_style_set): recreate the label's
+       layout when the style is set, since fonts etc. could have changed.      
+
 Fri Feb 16 14:22:05 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/Makefile.am: Removed gtktreemodelsimple.[ch]
+
        * gtk/gtktreemodelsimple.[ch]: removes
 
 2001-02-16  Alexander Larsson  <alexl@redhat.com>
index 5a0cdd22cd8d80b5eab35459152efd243a09478f..b495a1029c5f472f1b7e50643288a91504cabfa8 100644 (file)
@@ -1,6 +1,46 @@
+2001-02-15  Havoc Pennington  <hp@redhat.com>
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): convert
+       the X coordinates so they're with respect to the line, rather than 
+       with respect to the layout.
+
+       * gtk/gtkalignment.c: Convert to new property API, patch from Lee
+       Mallabone
+
+       * gtk/testgtk.c (create_range_controls): add vscale tests, 
+       and inverted test
+
+       * gtk/gtkrange.c (gtk_range_set_inverted): new function to fix 
+       #50806
+
+       * gtk/gtkentry.c (gtk_entry_get_text): add G_CONST_RETURN
+
+       * gtk/gtktextiter.h (gtk_text_iter_is_last): rename 
+       gtk_text_iter_is_end
+
+       * gtk/gtktextbuffer.h (gtk_text_buffer_get_last_iter):
+       rename gtk_text_buffer_get_end_iter
+
+       * gtk/testgtk.c (create_labels): Add test for selectable
+
+       * gtk/gtkentry.c (gtk_entry_draw_text): Use new GDK API to draw
+       the selection stuff. This code is kind of broken since it doesn't 
+       use the theme engine.
+
+       * gdk/gdkpango.c (gdk_pango_layout_line_get_clip_region): 
+       fix infinite loop and y offset problem
+       (gdk_draw_layout_line_with_colors): fix foreground color handling
+
+        * gtk/gtklabel.h, gtk/gtklabel.c: Implement a "selectable" flag 
+       that makes the label selectable.
+       
+       * gtk/gtklabel.c (gtk_label_style_set): recreate the label's
+       layout when the style is set, since fonts etc. could have changed.      
+
 Fri Feb 16 14:22:05 2001  Jonathan Blandford  <jrb@redhat.com>
 
        * gtk/Makefile.am: Removed gtktreemodelsimple.[ch]
+
        * gtk/gtktreemodelsimple.[ch]: removes
 
 2001-02-16  Alexander Larsson  <alexl@redhat.com>
index 7a7c7d1aa37bf1c48e67af8d0987a4e0cc7dc124..7146880c78765cc3395593a97e7255d046729130 100644 (file)
@@ -259,7 +259,7 @@ gdk_draw_layout_line_with_colors (GdkDrawable      *drawable,
               tmp.green = foreground->green;
             }
           
-          fg_gc = gdk_pango_get_gc (context, fg_set ? &fg_color : NULL,
+          fg_gc = gdk_pango_get_gc (context, fg_set ? &tmp : NULL,
                                     stipple, gc);
         }
       else
@@ -656,10 +656,15 @@ gdk_pango_attr_embossed_new (gboolean embossed)
  * @index_ranges: array of byte indexes into the layout, where even members of array are start indexes and odd elements are end indexes
  * @n_ranges: number of ranges in @index_ranges, i.e. half the size of @index_ranges
  * 
- * Obtains a clip region which contains the areas where the given ranges
- * of text would be drawn. @x_origin and @y_origin are the same position
- * you would pass to gdk_draw_layout_line(). @index_ranges should contain
- * ranges of bytes in the layout's text.
+ * Obtains a clip region which contains the areas where the given
+ * ranges of text would be drawn. @x_origin and @y_origin are the same
+ * position you would pass to gdk_draw_layout_line(). @index_ranges
+ * should contain ranges of bytes in the layout's text. The clip
+ * region will include space to the left or right of the line (to the
+ * layout bounding box) if you have indexes above or below the indexes
+ * contained inside the line. This is to draw the selection all the way
+ * to the side of the layout. However, the clip region is in line coordinates,
+ * not layout coordinates.
  * 
  * Return value: a clip region containing the given ranges
  **/
@@ -673,13 +678,20 @@ gdk_pango_layout_line_get_clip_region (PangoLayoutLine *line,
   GdkRegion *clip_region;
   gint i;
   PangoRectangle logical_rect;
+  PangoLayoutIter *iter;
+  gint baseline;
   
   g_return_val_if_fail (line != NULL, NULL);
   g_return_val_if_fail (index_ranges != NULL, NULL);
   
   clip_region = gdk_region_new ();
 
-  pango_layout_line_get_extents (line, NULL, &logical_rect);
+  iter = pango_layout_get_iter (line->layout);
+  while (pango_layout_iter_get_line (iter) != line)
+    pango_layout_iter_next_line (iter);
+  
+  pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+  baseline = pango_layout_iter_get_baseline (iter);
   
   i = 0;
   while (i < n_ranges)
@@ -687,7 +699,9 @@ gdk_pango_layout_line_get_clip_region (PangoLayoutLine *line,
       gint *pixel_ranges = NULL;
       gint n_pixel_ranges = 0;
       gint j;
-      
+
+      /* Note that get_x_ranges returns layout coordinates
+       */
       pango_layout_line_get_x_ranges (line,
                                       index_ranges[i*2],
                                       index_ranges[i*2+1],
@@ -696,16 +710,17 @@ gdk_pango_layout_line_get_clip_region (PangoLayoutLine *line,
       for (j=0; j < n_pixel_ranges; j++)
         {
           GdkRectangle rect;
-      
-          rect.x = x_origin + pixel_ranges[2*j] / PANGO_SCALE;
-          rect.y = y_origin - logical_rect.y / PANGO_SCALE;
+          
+          rect.x = x_origin + pixel_ranges[2*j] / PANGO_SCALE - logical_rect.x / PANGO_SCALE;
+          rect.y = y_origin - (baseline / PANGO_SCALE - logical_rect.y / PANGO_SCALE);
           rect.width = (pixel_ranges[2*j + 1] - pixel_ranges[2*j]) / PANGO_SCALE;
-          rect.height = logical_rect.height / PANGO_SCALE;      
-      
+          rect.height = logical_rect.height / PANGO_SCALE;
+          
           gdk_region_union_with_rect (clip_region, &rect);
         }
 
       g_free (pixel_ranges);
+      ++i;
     }
 
   return clip_region;
@@ -750,8 +765,8 @@ gdk_pango_layout_get_clip_region (PangoLayout *layout,
       GdkRegion *line_region;
       gint baseline;
       
-      line = pango_layout_iter_get_line (iter);
-      
+      line = pango_layout_iter_get_line (iter);      
+
       pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
       baseline = pango_layout_iter_get_baseline (iter);      
 
index 54c49ee38fb7e43c84e788065b9bf56b439a86b3..8d9cb05ee2974cb7876b94354ef424eeaeb69c26 100644 (file)
  */
 
 #include "gtkalignment.h"
-
+#include "gtkintl.h"
 
 enum {
-  ARG_0,
-  ARG_XALIGN,
-  ARG_YALIGN,
-  ARG_XSCALE,
-  ARG_YSCALE
+  PROP_0,
+
+  PROP_XALIGN,
+  PROP_YALIGN,
+  PROP_XSCALE,
+  PROP_YSCALE,
+  
+  PROP_LAST
 };
 
 
@@ -42,14 +45,16 @@ static void gtk_alignment_size_request  (GtkWidget         *widget,
                                         GtkRequisition    *requisition);
 static void gtk_alignment_size_allocate (GtkWidget         *widget,
                                         GtkAllocation     *allocation);
-static void gtk_alignment_set_arg       (GtkObject         *object,
-                                        GtkArg            *arg,
-                                        guint              arg_id);
-static void gtk_alignment_get_arg       (GtkObject         *object,
-                                        GtkArg            *arg,
-                                        guint              arg_id);
-
-
+static void gtk_alignment_set_property (GObject         *object,
+                                        guint            prop_id,
+                                        const GValue    *value,
+                                        GParamSpec      *pspec,
+                                        const gchar     *trailer);
+static void gtk_alignment_get_property (GObject         *object,
+                                        guint            prop_id,
+                                        GValue          *value,
+                                        GParamSpec      *pspec,
+                                        const gchar     *trailer);
 
 GtkType
 gtk_alignment_get_type (void)
@@ -85,13 +90,46 @@ gtk_alignment_class_init (GtkAlignmentClass *class)
   object_class = (GtkObjectClass*) class;
   widget_class = (GtkWidgetClass*) class;
 
-  gtk_object_add_arg_type ("GtkAlignment::xalign", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_XALIGN);
-  gtk_object_add_arg_type ("GtkAlignment::yalign", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_YALIGN);
-  gtk_object_add_arg_type ("GtkAlignment::xscale", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_XSCALE);
-  gtk_object_add_arg_type ("GtkAlignment::yscale", GTK_TYPE_FLOAT, GTK_ARG_READWRITE, ARG_YSCALE);
-
-  object_class->set_arg = gtk_alignment_set_arg;
-  object_class->get_arg = gtk_alignment_get_arg;
+  g_object_class_install_property(G_OBJECT_CLASS(object_class),
+                                 PROP_XALIGN,
+                                 g_param_spec_float("xalign",
+                                                    _("Horizontal alignment"),
+                                                    _("Value between 0.0 and 1.0 to indicate X alignment"),
+                                                    0.0,
+                                                    1.0,
+                                                    0.5,
+                                                    G_PARAM_READABLE | G_PARAM_WRITABLE));
+   
+  g_object_class_install_property(G_OBJECT_CLASS(object_class),
+                                 PROP_YALIGN,
+                                 g_param_spec_float("yalign",
+                                                    _("Vertical alignment"),
+                                                    _("Value between 0.0 and 1.0 to indicate Y alignment"),
+                                                    0.0,
+                                                    1.0,
+                                                     0.5,
+                                                    G_PARAM_READABLE | G_PARAM_WRITABLE));
+  g_object_class_install_property(G_OBJECT_CLASS(object_class),
+                                 PROP_XSCALE,
+                                 g_param_spec_float("xscale",
+                                                    _("Horizontal scale"),
+                                                    _("Value between 0.0 and 1.0 to indicate X scale"),
+                                                    0.0,
+                                                    1.0,
+                                                    0.5,
+                                                    G_PARAM_READABLE | G_PARAM_WRITABLE));
+  g_object_class_install_property(G_OBJECT_CLASS(object_class),
+                                 PROP_YSCALE,
+                                 g_param_spec_float("yscale",
+                                                    _("Vertical scale"),
+                                                    _("Value between 0.0 and 1.0 to indicate Y scale"),
+                                                    0.0,
+                                                    1.0,
+                                                    0.5,
+                                                    G_PARAM_READABLE | G_PARAM_WRITABLE));
+   
+  G_OBJECT_CLASS(object_class)->set_property = gtk_alignment_set_property;
+  G_OBJECT_CLASS(object_class)->get_property = gtk_alignment_get_property;
 
   widget_class->size_request = gtk_alignment_size_request;
   widget_class->size_allocate = gtk_alignment_size_allocate;
@@ -126,75 +164,79 @@ gtk_alignment_new (gfloat xalign,
   return GTK_WIDGET (alignment);
 }
 
-static void
-gtk_alignment_set_arg (GtkObject         *object,
-                      GtkArg            *arg,
-                      guint              arg_id)
+static void gtk_alignment_set_property (GObject         *object,
+                                        guint            prop_id,
+                                        const GValue    *value,
+                                        GParamSpec      *pspec,
+                                        const gchar     *trailer)
 {
   GtkAlignment *alignment;
 
   alignment = GTK_ALIGNMENT (object);
 
-  switch (arg_id)
+  switch (prop_id)
     {
-    case ARG_XALIGN:
+    case PROP_XALIGN:
       gtk_alignment_set (alignment,
-                        GTK_VALUE_FLOAT (*arg),
+                        g_value_get_float(value),
                         alignment->yalign,
                         alignment->xscale,
                         alignment->yscale);
       break;
-    case ARG_YALIGN:
+    case PROP_YALIGN:
       gtk_alignment_set (alignment,
                         alignment->xalign,
-                        GTK_VALUE_FLOAT (*arg),
+                        g_value_get_float(value),
                         alignment->xscale,
                         alignment->yscale);
       break;
-    case ARG_XSCALE:
+    case PROP_XSCALE:
       gtk_alignment_set (alignment,
                         alignment->xalign,
                         alignment->yalign,
-                        GTK_VALUE_FLOAT (*arg),
+                        g_value_get_float(value),
                         alignment->yscale);
       break;
-    case ARG_YSCALE:
+    case PROP_YSCALE:
       gtk_alignment_set (alignment,
                         alignment->xalign,
                         alignment->yalign,
                         alignment->xscale,
-                        GTK_VALUE_FLOAT (*arg));
+                        g_value_get_float(value));
       break;
     default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
     }
 }
 
-static void
-gtk_alignment_get_arg (GtkObject         *object,
-                      GtkArg            *arg,
-                      guint              arg_id)
+static void gtk_alignment_get_property (GObject         *object,
+                                        guint            prop_id,
+                                        GValue          *value,
+                                        GParamSpec      *pspec,
+                                        const gchar     *trailer)
 {
   GtkAlignment *alignment;
 
   alignment = GTK_ALIGNMENT (object);
-
-  switch (arg_id)
+  g_assert (GTK_IS_ALIGNMENT(object));
+   
+  switch (prop_id)
     {
-    case ARG_XALIGN:
-      GTK_VALUE_FLOAT (*arg) = alignment->xalign;
+    case PROP_XALIGN:
+      g_value_set_float(value, alignment->xalign);
       break;
-    case ARG_YALIGN:
-      GTK_VALUE_FLOAT (*arg) = alignment->yalign;
+    case PROP_YALIGN:
+      g_value_set_float(value, alignment->yalign);
       break;
-    case ARG_XSCALE:
-      GTK_VALUE_FLOAT (*arg) = alignment->xscale;
+    case PROP_XSCALE:
+      g_value_set_float(value, alignment->xscale);
       break;
-    case ARG_YSCALE:
-      GTK_VALUE_FLOAT (*arg) = alignment->yscale;
+    case PROP_YSCALE:
+      g_value_set_float(value, alignment->yscale);
       break;
     default:
-      arg->type = GTK_TYPE_INVALID;
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
     }
 }
@@ -206,6 +248,8 @@ gtk_alignment_set (GtkAlignment *alignment,
                   gfloat        xscale,
                   gfloat        yscale)
 {
+  gboolean values_changed = FALSE; 
+  
   g_return_if_fail (alignment != NULL);
   g_return_if_fail (GTK_IS_ALIGNMENT (alignment));
 
@@ -214,16 +258,33 @@ gtk_alignment_set (GtkAlignment *alignment,
   xscale = CLAMP (xscale, 0.0, 1.0);
   yscale = CLAMP (yscale, 0.0, 1.0);
 
-  if ((alignment->xalign != xalign) ||
-      (alignment->yalign != yalign) ||
-      (alignment->xscale != xscale) ||
-      (alignment->yscale != yscale))
+  if (alignment->xalign != xalign)
+    {
+       values_changed = TRUE;
+       alignment->xalign = xalign;
+       g_object_notify(G_OBJECT(alignment), "xalign");
+    }
+  if (alignment->yalign != yalign)
+    {
+       values_changed = TRUE;
+       alignment->yalign = yalign;
+       g_object_notify(G_OBJECT(alignment), "yalign");
+    }
+  if (alignment->xscale != xscale)
     {
-      alignment->xalign = xalign;
-      alignment->yalign = yalign;
-      alignment->xscale = xscale;
-      alignment->yscale = yscale;
+       values_changed = TRUE;
+       alignment->xscale = xscale;
+       g_object_notify(G_OBJECT(alignment), "xscale");
+    }
+  if (alignment->yscale != yscale)
+    {
+       values_changed = TRUE;
+       alignment->yscale = yscale;
+       g_object_notify(G_OBJECT(alignment), "yscale");
+    }
 
+   if (values_changed == TRUE)
+    {
       gtk_widget_size_allocate (GTK_WIDGET (alignment), &(GTK_WIDGET (alignment)->allocation));
       gtk_widget_queue_draw (GTK_WIDGET (alignment));
     }
index 76929a745543c9c8502e376bea39f66dc8749fb6..75c486649cae9e23c2547d1deaa34829beb21846 100644 (file)
@@ -2619,7 +2619,7 @@ gtk_entry_set_editable(GtkEntry *entry,
   gtk_editable_set_editable (GTK_EDITABLE (entry), editable);
 }
 
-gchar*
+G_CONST_RETURN gchar*
 gtk_entry_get_text (GtkEntry *entry)
 {
   g_return_val_if_fail (entry != NULL, NULL);
index c8dbcdd8359732d9eddcc7628cf690ba7d5a9ce2..f9352ce8053b730a06a65de5803bdcf01c6d9918 100644 (file)
@@ -149,10 +149,10 @@ void       gtk_entry_set_max_length               (GtkEntry      *entry,
 
 /* Somewhat more convenient than the GtkEditable generic functions
  */
-void       gtk_entry_set_text                  (GtkEntry      *entry,
-                                                const gchar   *text);
+void                  gtk_entry_set_text        (GtkEntry      *entry,
+                                                 const gchar   *text);
 /* returns a reference to the text */
-gchar*     gtk_entry_get_text                  (GtkEntry      *entry);
+G_CONST_RETURN gchar* gtk_entry_get_text        (GtkEntry      *entry);
 
 /* Deprecated compatibility functions
  */
index d8ff48516ed6b8892d4491ddd071dec6e6ff69bf..bef3322efcaaca82f6244b5b0d9faa6fd90fd530 100644 (file)
 #include <string.h>
 #include "gtklabel.h"
 #include "gdk/gdkkeysyms.h"
+#include "gtkclipboard.h"
 #include "gdk/gdki18n.h"
 #include <pango/pango.h>
 
+struct _GtkLabelSelectionInfo
+{
+  GdkWindow *window;
+  gint selection_anchor;
+  gint selection_end;
+};
 
 enum {
   ARG_0,
@@ -50,6 +57,8 @@ static void gtk_label_get_arg           (GtkObject        *object,
 static void gtk_label_finalize          (GObject          *object);
 static void gtk_label_size_request      (GtkWidget        *widget,
                                         GtkRequisition   *requisition);
+static void gtk_label_size_allocate     (GtkWidget        *widget,
+                                         GtkAllocation    *allocation);
 static void gtk_label_style_set         (GtkWidget        *widget,
                                         GtkStyle         *previous_style);
 static void gtk_label_direction_changed (GtkWidget        *widget,
@@ -57,7 +66,29 @@ static void gtk_label_direction_changed (GtkWidget        *widget,
 static gint gtk_label_expose            (GtkWidget        *widget,
                                         GdkEventExpose   *event);
 
-static GtkMiscClass *parent_class = NULL;
+static void gtk_label_realize           (GtkWidget        *widget);
+static void gtk_label_unrealize         (GtkWidget        *widget);
+static void gtk_label_map               (GtkWidget        *widget);
+static void gtk_label_unmap             (GtkWidget        *widget);
+static gint gtk_label_button_press      (GtkWidget        *widget,
+                                         GdkEventButton   *event);
+static gint gtk_label_button_release    (GtkWidget        *widget,
+                                         GdkEventButton   *event);
+static gint gtk_label_motion            (GtkWidget        *widget,
+                                         GdkEventMotion   *event);
+
+static void gtk_label_create_window       (GtkLabel *label);
+static void gtk_label_destroy_window      (GtkLabel *label);
+static void gtk_label_clear_layout        (GtkLabel *label);
+static void gtk_label_ensure_layout       (GtkLabel *label,
+                                           gint     *widthp,
+                                           gint     *heightp);
+static void gtk_label_select_region_index (GtkLabel *label,
+                                           gint      anchor_index,
+                                           gint      end_index);
+
+
+GtkMiscClass *parent_class = NULL;
 
 GtkType
 gtk_label_get_type (void)
@@ -108,9 +139,17 @@ gtk_label_class_init (GtkLabelClass *class)
   object_class->get_arg = gtk_label_get_arg;
   
   widget_class->size_request = gtk_label_size_request;
+  widget_class->size_allocate = gtk_label_size_allocate;
   widget_class->style_set = gtk_label_style_set;
   widget_class->direction_changed = gtk_label_direction_changed;
   widget_class->expose_event = gtk_label_expose;
+  widget_class->realize = gtk_label_realize;
+  widget_class->unrealize = gtk_label_unrealize;
+  widget_class->map = gtk_label_map;
+  widget_class->unmap = gtk_label_unmap;
+  widget_class->button_press_event = gtk_label_button_press;
+  widget_class->button_release_event = gtk_label_button_release;
+  widget_class->motion_notify_event = gtk_label_motion;
 }
 
 static void
@@ -207,11 +246,10 @@ gtk_label_set_text_internal (GtkLabel *label,
   g_free (label->label);
   
   label->label = str;
-  if (label->layout)
-    {
-      g_object_unref (G_OBJECT (label->layout));
-      label->layout = NULL;
-    }
+
+  gtk_label_clear_layout (label);  
+
+  gtk_label_select_region_index (label, 0, 0);
   
   gtk_widget_queue_resize (GTK_WIDGET (label));
 }
@@ -426,6 +464,8 @@ gtk_label_finalize (GObject *object)
 
   if (label->attrs)
     pango_attr_list_unref (label->attrs);
+
+  g_free (label->select_info);
   
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -469,16 +509,25 @@ gtk_label_pattern_to_attrs (GtkLabel      *label,
 }
 
 static void
-gtk_label_size_request (GtkWidget      *widget,
-                       GtkRequisition *requisition)
+gtk_label_clear_layout (GtkLabel *label)
 {
-  GtkLabel *label;
+  if (label->layout)
+    {
+      g_object_unref (G_OBJECT (label->layout));
+      label->layout = NULL;
+    }
+}
+
+static void
+gtk_label_ensure_layout (GtkLabel *label,
+                         gint     *widthp,
+                         gint     *heightp)
+{
+  GtkWidget *widget;
   PangoRectangle logical_rect;
-  
-  g_return_if_fail (GTK_IS_LABEL (widget));
-  g_return_if_fail (requisition != NULL);
-  
-  label = GTK_LABEL (widget);
+  gint width, height;
+
+  widget = GTK_WIDGET (label);
 
   /*
    * There are a number of conditions which will necessitate re-filling
@@ -501,8 +550,8 @@ gtk_label_size_request (GtkWidget      *widget,
    * don't think it's really that slow.
    */
 
-  requisition->width = label->misc.xpad * 2;
-  requisition->height = label->misc.ypad * 2;
+  width = label->misc.xpad * 2;
+  height = label->misc.ypad * 2;
 
   if (!label->layout)
     {
@@ -512,7 +561,7 @@ gtk_label_size_request (GtkWidget      *widget,
       label->layout = gtk_widget_create_pango_layout (widget, label->label);
 
       /* FIXME move to a model where the pattern isn't stored
-       * permanently, and just modifes or creates the AttrList
+       * permanently, and just modifies or creates the AttrList
        */
       if (label->attrs)
        attrs = pango_attr_list_copy (label->attrs);
@@ -521,7 +570,7 @@ gtk_label_size_request (GtkWidget      *widget,
 
       if (label->pattern)
        gtk_label_pattern_to_attrs (label, attrs);
-
+      
       if (attrs)
        {
          pango_layout_set_attributes (label->layout, attrs);
@@ -564,8 +613,8 @@ gtk_label_size_request (GtkWidget      *widget,
          pango_layout_set_width (label->layout, aux_info->width * PANGO_SCALE);
          pango_layout_get_extents (label->layout, NULL, &logical_rect);
 
-         requisition->width += aux_info->width;
-         requisition->height += PANGO_PIXELS (logical_rect.height);
+         width += aux_info->width;
+         height += PANGO_PIXELS (logical_rect.height);
        }
       else
        {
@@ -632,8 +681,8 @@ gtk_label_size_request (GtkWidget      *widget,
            }
          pango_layout_set_width (label->layout, width);
 
-         requisition->width += PANGO_PIXELS (real_width);
-         requisition->height += PANGO_PIXELS (height);
+         width += PANGO_PIXELS (real_width);
+         height += PANGO_PIXELS (height);
        }
     }
   else                         /* !label->wrap */
@@ -641,8 +690,52 @@ gtk_label_size_request (GtkWidget      *widget,
       pango_layout_set_width (label->layout, -1);
       pango_layout_get_extents (label->layout, NULL, &logical_rect);
 
-      requisition->width += PANGO_PIXELS (logical_rect.width);
-      requisition->height += PANGO_PIXELS (logical_rect.height);
+      width += PANGO_PIXELS (logical_rect.width);
+      height += PANGO_PIXELS (logical_rect.height);
+    }
+
+  if (widthp)
+    *widthp = width;
+
+  if (heightp)
+    *heightp = height;
+}
+
+static void
+gtk_label_size_request (GtkWidget      *widget,
+                       GtkRequisition *requisition)
+{
+  GtkLabel *label;
+  gint width, height;
+  
+  g_return_if_fail (GTK_IS_LABEL (widget));
+  g_return_if_fail (requisition != NULL);
+  
+  label = GTK_LABEL (widget);
+
+  gtk_label_ensure_layout (label, &width, &height);
+
+  requisition->width = width;
+  requisition->height = height;
+}
+
+static void
+gtk_label_size_allocate (GtkWidget     *widget,
+                         GtkAllocation *allocation)
+{
+  GtkLabel *label;
+
+  label = GTK_LABEL (widget);
+  
+  (* GTK_WIDGET_CLASS (parent_class)->size_allocate) (widget, allocation);
+
+  if (label->select_info && label->select_info->window)
+    {
+      gdk_window_move_resize (label->select_info->window,
+                              allocation->x,
+                              allocation->y,
+                              allocation->width,
+                              allocation->height);
     }
 }
 
@@ -651,13 +744,13 @@ gtk_label_style_set (GtkWidget *widget,
                     GtkStyle  *previous_style)
 {
   GtkLabel *label;
-
+  
   g_return_if_fail (GTK_IS_LABEL (widget));
   
   label = GTK_LABEL (widget);
 
-  if (previous_style && label->layout)
-    pango_layout_context_changed (label->layout);
+  /* We have to clear the layout, fonts etc. may have changed */
+  gtk_label_clear_layout (label);
 }
 
 static void 
@@ -703,42 +796,58 @@ gtk_label_paint_word (GtkLabel     *label,
 }
 #endif
 
+static void
+get_layout_location (GtkLabel  *label,
+                     gint      *xp,
+                     gint      *yp)
+{
+  GtkMisc *misc;
+  GtkWidget *widget;
+  gfloat xalign;
+  gint x, y;
+  
+  misc = GTK_MISC (label);
+  widget = GTK_WIDGET (label);
+  
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
+    xalign = misc->xalign;
+  else
+    xalign = 1.0 - misc->xalign;
+  
+  x = floor (widget->allocation.x + (gint)misc->xpad
+             + ((widget->allocation.width - widget->requisition.width) * xalign)
+             + 0.5);
+  
+  y = floor (widget->allocation.y + (gint)misc->ypad 
+             + ((widget->allocation.height - widget->requisition.height) * misc->yalign)
+             + 0.5);
+  
+
+  if (xp)
+    *xp = x;
+
+  if (yp)
+    *yp = y;
+}
+
 static gint
 gtk_label_expose (GtkWidget      *widget,
                  GdkEventExpose *event)
 {
   GtkLabel *label;
-  GtkMisc *misc;
   gint x, y;
-  gfloat xalign;
   
   g_return_val_if_fail (GTK_IS_LABEL (widget), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
   
   label = GTK_LABEL (widget);
 
-  /* if label->layout is NULL it means we got a set_text since
-   * our last size request, so a resize should be queued,
-   * which means a full expose is in the queue anyway.
-   */
+  gtk_label_ensure_layout (label, NULL, NULL);
+  
   if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget) &&
-      label->layout && label->label && (*label->label != '\0'))
+      label->label && (*label->label != '\0'))
     {
-      misc = GTK_MISC (widget);
-      
-      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
-       xalign = misc->xalign;
-      else
-       xalign = 1. - misc->xalign;
-      
-      x = floor (widget->allocation.x + (gint)misc->xpad
-                + ((widget->allocation.width - widget->requisition.width) * xalign)
-                + 0.5);
-      
-      y = floor (widget->allocation.y + (gint)misc->ypad 
-                + ((widget->allocation.height - widget->requisition.height) * misc->yalign)
-                + 0.5);
-
+      get_layout_location (label, &x, &y);
       
       gtk_paint_layout (widget->style,
                         widget->window,
@@ -748,6 +857,45 @@ gtk_label_expose (GtkWidget      *widget,
                         "label",
                         x, y,
                         label->layout);
+      
+      if (label->select_info &&
+          (label->select_info->selection_anchor !=
+           label->select_info->selection_end))
+        {
+          gint range[2];
+          GdkRegion *clip;
+          
+          range[0] = label->select_info->selection_anchor;
+          range[1] = label->select_info->selection_end;
+
+          if (range[0] > range[1])
+            {
+              gint tmp = range[0];
+              range[0] = range[1];
+              range[1] = tmp;
+            }
+
+          clip = gdk_pango_layout_get_clip_region (label->layout,
+                                                   x, y,
+                                                   range,
+                                                   1);
+
+          /* FIXME should use gtk_paint, but it can't use a clip
+           * region
+           */
+
+          gdk_gc_set_clip_region (widget->style->white_gc, clip);
+          
+          gdk_draw_layout_with_colors (widget->window,
+                                       widget->style->white_gc,
+                                       x, y,
+                                       label->layout,
+                                       &widget->style->fg[GTK_STATE_SELECTED],
+                                       &widget->style->bg[GTK_STATE_SELECTED]);
+
+          gdk_gc_set_clip_region (widget->style->white_gc, NULL);
+          gdk_region_destroy (clip);
+        }
     }
 
   return TRUE;
@@ -836,3 +984,443 @@ gtk_label_parse_uline (GtkLabel    *label,
   
   return accel_key;
 }
+
+static void
+gtk_label_realize (GtkWidget *widget)
+{
+  GtkLabel *label;
+
+  label = GTK_LABEL (widget);
+  
+  (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
+
+  if (label->select_info)
+    gtk_label_create_window (label);
+}
+
+static void
+gtk_label_unrealize (GtkWidget *widget)
+{
+  GtkLabel *label;
+
+  label = GTK_LABEL (widget);
+
+  if (label->select_info)
+    gtk_label_destroy_window (label);
+  
+  (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
+gtk_label_map (GtkWidget *widget)
+{
+  GtkLabel *label;
+
+  label = GTK_LABEL (widget);
+  
+  (* GTK_WIDGET_CLASS (parent_class)->map) (widget);
+  
+  if (label->select_info)
+    gdk_window_show (label->select_info->window);
+}
+
+static void
+gtk_label_unmap (GtkWidget *widget)
+{
+  GtkLabel *label;
+
+  label = GTK_LABEL (widget);
+
+  if (label->select_info)
+    gdk_window_hide (label->select_info->window);
+  
+  (* GTK_WIDGET_CLASS (parent_class)->unmap) (widget);
+}
+
+static void
+window_to_layout_coords (GtkLabel *label,
+                         gint     *x,
+                         gint     *y)
+{
+  gint lx, ly;
+  GtkWidget *widget;
+
+  widget = GTK_WIDGET (label);
+  
+  /* get layout location in widget->window coords */
+  get_layout_location (label, &lx, &ly);
+  
+  if (x)
+    {
+      *x += widget->allocation.x; /* go to widget->window */
+      *x -= lx;                   /* go to layout */
+    }
+
+  if (y)
+    {
+      *y += widget->allocation.y; /* go to widget->window */
+      *y -= ly;                   /* go to layout */
+    }
+}
+
+static void
+layout_to_window_coords (GtkLabel *label,
+                         gint     *x,
+                         gint     *y)
+{
+  gint lx, ly;
+  GtkWidget *widget;
+
+  widget = GTK_WIDGET (label);
+  
+  /* get layout location in widget->window coords */
+  get_layout_location (label, &lx, &ly);
+  
+  if (x)
+    {
+      *x += lx;                   /* go to widget->window */
+      *x -= widget->allocation.x; /* go to selection window */
+    }
+
+  if (y)
+    {
+      *y += ly;                   /* go to widget->window */
+      *y -= widget->allocation.y; /* go to selection window */
+    }
+}
+
+static void
+get_layout_index (GtkLabel *label,
+                  gint      x,
+                  gint      y,
+                  gint     *index)
+{
+  gint trailing = 0;
+  const gchar *cluster;
+  const gchar *cluster_end;
+
+  *index = 0;
+  
+  gtk_label_ensure_layout (label, NULL, NULL);
+  
+  window_to_layout_coords (label, &x, &y);
+
+  x *= PANGO_SCALE;
+  y *= PANGO_SCALE;
+  
+  pango_layout_xy_to_index (label->layout,
+                            x, y,
+                            index, &trailing);
+
+  
+  cluster = label->label + *index;
+  cluster_end = cluster;
+  while (trailing)
+    {
+      cluster_end = g_utf8_next_char (cluster_end);
+      --trailing;
+    }
+
+  *index += (cluster_end - cluster);
+}
+
+static gint
+gtk_label_button_press (GtkWidget      *widget,
+                        GdkEventButton *event)
+{
+  GtkLabel *label;
+  gint index = 0;
+  
+  label = GTK_LABEL (widget);
+
+  if (label->select_info == NULL)
+    return FALSE;
+
+  if (event->button != 1)
+    return FALSE;
+
+  get_layout_index (label, event->x, event->y, &index);
+  
+  if ((label->select_info->selection_anchor !=
+       label->select_info->selection_end) &&
+      (event->state & GDK_SHIFT_MASK))
+    {
+      /* extend (same as motion) */
+      if (index < label->select_info->selection_end)
+        gtk_label_select_region_index (label,
+                                       index,
+                                       label->select_info->selection_end);
+      else
+        gtk_label_select_region_index (label,
+                                       label->select_info->selection_anchor,
+                                       index);
+
+      /* ensure the anchor is opposite index */
+      if (index == label->select_info->selection_anchor)
+        {
+          gint tmp = label->select_info->selection_end;
+          label->select_info->selection_end = label->select_info->selection_anchor;
+          label->select_info->selection_anchor = tmp;
+        }
+    }
+  else
+    {
+      /* start a replacement */
+      gtk_label_select_region_index (label, index, index);
+    }
+  
+  return TRUE;
+}
+
+static gint
+gtk_label_button_release (GtkWidget      *widget,
+                          GdkEventButton *event)
+
+{
+  GtkLabel *label;
+
+  label = GTK_LABEL (widget);
+  
+  if (label->select_info == NULL)
+    return FALSE;
+  
+  if (event->button != 1)
+    return FALSE;
+  
+  /* The goal here is to return TRUE iff we ate the
+   * button press to start selecting.
+   */
+  
+  return TRUE;
+}
+
+static gint
+gtk_label_motion (GtkWidget      *widget,
+                  GdkEventMotion *event)
+{
+  GtkLabel *label;
+  gint index;
+  gint x, y;
+  
+  label = GTK_LABEL (widget);
+  
+  if (label->select_info == NULL)
+    return FALSE;  
+
+  if ((event->state & GDK_BUTTON1_MASK) == 0)
+    return FALSE;
+
+  gdk_window_get_pointer (label->select_info->window,
+                          &x, &y, NULL);
+  
+  get_layout_index (label, x, y, &index);
+
+  gtk_label_select_region_index (label,
+                                 label->select_info->selection_anchor,
+                                 index);
+  
+  return TRUE;
+}
+
+static void
+gtk_label_create_window (GtkLabel *label)
+{
+  GtkWidget *widget;
+  GdkWindowAttr attributes;
+  gint attributes_mask;
+  
+  g_assert (label->select_info);
+  g_assert (GTK_WIDGET_REALIZED (label));
+  
+  if (label->select_info->window)
+    return;
+  
+  widget = GTK_WIDGET (label);
+
+  attributes.x = widget->allocation.x;
+  attributes.y = widget->allocation.y;
+  attributes.width = widget->allocation.width;
+  attributes.height = widget->allocation.height;
+  attributes.window_type = GDK_WINDOW_TEMP;
+  attributes.wclass = GDK_INPUT_ONLY;
+  attributes.override_redirect = TRUE;
+  attributes.event_mask = gtk_widget_get_events (widget) |
+    GDK_BUTTON_PRESS_MASK        |
+    GDK_BUTTON_RELEASE_MASK      |
+    GDK_BUTTON_MOTION_MASK;
+
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
+
+  label->select_info->window = gdk_window_new (widget->window,
+                                               &attributes, attributes_mask);
+  gdk_window_set_user_data (label->select_info->window, widget);  
+}
+
+static void
+gtk_label_destroy_window (GtkLabel *label)
+{
+  g_assert (label->select_info);
+
+  if (label->select_info->window == NULL)
+    return;
+  
+  gdk_window_set_user_data (label->select_info->window, NULL);
+  gdk_window_destroy (label->select_info->window);
+  label->select_info->window = NULL;
+}
+
+void
+gtk_label_set_selectable (GtkLabel *label,
+                          gboolean  setting)
+{
+  g_return_if_fail (GTK_IS_LABEL (label));
+  
+  setting = setting != FALSE;
+
+  if (setting)
+    {
+      if (label->select_info == NULL)
+        {
+          label->select_info = g_new (GtkLabelSelectionInfo, 1);
+
+          label->select_info->window = NULL;
+          label->select_info->selection_anchor = 0;
+          label->select_info->selection_end = 0;
+
+          if (GTK_WIDGET_REALIZED (label))
+            gtk_label_create_window (label);
+
+          if (GTK_WIDGET_MAPPED (label))
+            gdk_window_show (label->select_info->window);
+        }
+    }
+  else
+    {
+      if (label->select_info)
+        {
+          if (label->select_info->window)
+            gtk_label_destroy_window (label);
+
+          g_free (label->select_info);
+
+          label->select_info = NULL;
+        }
+    }
+}
+
+gboolean
+gtk_label_get_selectable (GtkLabel *label)
+{
+  g_return_val_if_fail (GTK_IS_LABEL (label), FALSE);
+
+  return label->select_info != NULL;
+}
+
+static void
+get_text_callback (GtkClipboard     *clipboard,
+                   GtkSelectionData *selection_data,
+                   guint             info,
+                   gpointer          user_data_or_owner)
+{
+  GtkLabel *label;
+  gchar *str;
+  
+  label = GTK_LABEL (user_data_or_owner);
+  
+  if ((label->select_info->selection_anchor !=
+       label->select_info->selection_end) &&
+      label->label)
+    {
+      gint start, end;
+      
+      start = MIN (label->select_info->selection_anchor,
+                   label->select_info->selection_end);
+      end = MAX (label->select_info->selection_anchor,
+                 label->select_info->selection_end);
+      
+      str = g_strndup (label->label + start,
+                       end - start);
+      
+      gtk_selection_data_set_text (selection_data, 
+                                   str);
+
+      g_free (str);
+    }
+}
+
+static void
+clear_text_callback (GtkClipboard     *clipboard,
+                     gpointer          user_data_or_owner)
+{
+  GtkLabel *label;
+
+  label = GTK_LABEL (user_data_or_owner);
+
+  if (label->select_info)
+    {
+      label->select_info->selection_anchor = 0;
+      label->select_info->selection_end = 0;
+      
+      gtk_label_clear_layout (label);
+      gtk_widget_queue_draw (GTK_WIDGET (label));
+    }
+}
+
+static void
+gtk_label_select_region_index (GtkLabel *label,
+                               gint      anchor_index,
+                               gint      end_index)
+{
+  static const GtkTargetEntry targets[] = {
+    { "STRING", 0, 0 },
+    { "TEXT",   0, 0 }, 
+    { "COMPOUND_TEXT", 0, 0 },
+    { "UTF8_STRING", 0, 0 }
+  };
+  
+  g_return_if_fail (GTK_IS_LABEL (label));
+  
+  if (label->select_info)
+    {
+      GtkClipboard *clipboard;
+
+      label->select_info->selection_anchor = anchor_index;
+      label->select_info->selection_end = end_index;
+
+      clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);      
+
+      gtk_clipboard_set_with_owner (clipboard,
+                                    targets,
+                                    G_N_ELEMENTS (targets),
+                                    get_text_callback,
+                                    clear_text_callback,
+                                    G_OBJECT (label));
+
+      gtk_label_clear_layout (label);
+      gtk_widget_queue_draw (GTK_WIDGET (label));
+    }
+}
+
+void
+gtk_label_select_region  (GtkLabel *label,
+                          gint      start_offset,
+                          gint      end_offset)
+{
+  g_return_if_fail (GTK_IS_LABEL (label));
+  
+  if (label->label && label->select_info)
+    {
+      GtkClipboard *clipboard;
+
+      if (start_offset < 0)
+        start_offset = 0;
+
+      if (end_offset < 0)
+        end_offset = g_utf8_strlen (label->label, -1);
+      
+      gtk_label_select_region_index (label,
+                                     g_utf8_offset_to_pointer (label->label, start_offset) - label->label,
+                                     g_utf8_offset_to_pointer (label->label, end_offset) - label->label);
+    }
+}
+
index 787ffed50f7f9b14b7277b700f661f42540eb9b8..6285670113dd4d5a30069ca73b69f83c396ea775 100644 (file)
@@ -47,19 +47,24 @@ extern "C" {
 typedef struct _GtkLabel       GtkLabel;
 typedef struct _GtkLabelClass  GtkLabelClass;
 
+typedef struct _GtkLabelSelectionInfo GtkLabelSelectionInfo;
+
 struct _GtkLabel
 {
   GtkMisc misc;
 
+  /*< private >*/
+  
   gchar    *label;
   gchar    *pattern;
 
   guint   jtype : 2;
   guint   wrap : 1;
   
-  /*< private >*/
   PangoLayout *layout;
   PangoAttrList *attrs;
+
+  GtkLabelSelectionInfo *select_info;
 };
 
 struct _GtkLabelClass
@@ -95,6 +100,14 @@ void       gtk_label_set_line_wrap (GtkLabel         *label,
 guint       gtk_label_parse_uline   (GtkLabel         *label,
                                     const gchar      *string);
 
+void     gtk_label_set_selectable (GtkLabel *label,
+                                   gboolean  setting);
+gboolean gtk_label_get_selectable (GtkLabel *label);
+
+void     gtk_label_select_region  (GtkLabel *label,
+                                   gint      start_offset,
+                                   gint      end_offset);
+
 #ifndef        GTK_DISABLE_COMPAT_H
 #  define gtk_label_set                                gtk_label_set_text
 #endif /* GTK_DISABLE_COMPAT_H */
index 77e43d221a1b275e85cbcafaa7a28d536c5681b6..66c3bbf9671f1f51ab24bd0f3e4d46cfd5d48c13 100644 (file)
@@ -305,6 +305,29 @@ gtk_range_set_adjustment (GtkRange      *range,
     }
 }
 
+void
+gtk_range_set_inverted (GtkRange *range,
+                        gboolean  setting)
+{
+  g_return_if_fail (GTK_IS_RANGE (range));
+  
+  setting = setting != FALSE;
+
+  if (setting != range->inverted)
+    {
+      range->inverted = setting;
+      gtk_widget_queue_resize (GTK_WIDGET (range));
+    }
+}
+
+gboolean
+gtk_range_get_inverted (GtkRange *range)
+{
+  g_return_val_if_fail (GTK_IS_RANGE (range), FALSE);
+
+  return range->inverted;
+}
+
 void
 gtk_range_draw_background (GtkRange *range)
 {
@@ -420,6 +443,19 @@ move_and_update_window (GdkWindow *window, gint x, gint y)
   gdk_window_process_updates (parent, TRUE);
 }
 
+static gboolean
+should_invert (GtkRange *range,
+               gboolean  horizontal)
+{  
+  if (horizontal)
+    return
+      (range->inverted && !range->flippable) ||
+      (range->inverted && range->flippable && gtk_widget_get_direction (GTK_WIDGET (range)) == GTK_TEXT_DIR_LTR) ||
+      (!range->inverted && range->flippable && gtk_widget_get_direction (GTK_WIDGET (range)) == GTK_TEXT_DIR_RTL);
+  else
+    return range->inverted;
+}
+
 void
 gtk_range_default_hslider_update (GtkRange *range)
 {
@@ -455,7 +491,7 @@ gtk_range_default_hslider_update (GtkRange *range)
       else if (x > right)
        x = right;
 
-      if (range->flippable && gtk_widget_get_direction (GTK_WIDGET (range)) == GTK_TEXT_DIR_RTL)
+      if (should_invert (range, TRUE))
        x = right - (x - left);
       
       move_and_update_window (range->slider, x, GTK_WIDGET (range)->style->ythickness);
@@ -497,6 +533,9 @@ gtk_range_default_vslider_update (GtkRange *range)
       else if (y > bottom)
        y = bottom;
 
+      if (should_invert (range, FALSE))
+       y = bottom - (y - top);
+      
       move_and_update_window (range->slider, GTK_WIDGET (range)->style->xthickness, y);
     }
 }
@@ -523,7 +562,7 @@ gtk_range_default_htrough_click (GtkRange *range,
   gdk_window_get_size (range->slider, &slider_length, NULL);
   right += slider_length;
 
-  if (range->flippable && gtk_widget_get_direction (GTK_WIDGET (range)) == GTK_TEXT_DIR_RTL)
+  if (should_invert (range, TRUE))
     x = (right - x) + left;
 
   if ((x > left) && (y > ythickness))
@@ -571,7 +610,10 @@ gtk_range_default_vtrough_click (GtkRange *range,
   gtk_range_trough_vdims (range, &top, &bottom);
   gdk_window_get_size (range->slider, NULL, &slider_length);
   bottom += slider_length;
-             
+
+  if (should_invert (range, FALSE))
+    y = (bottom - y) + top;
+  
   if ((x > xthickness) && (y > top))
     {
       gdk_window_get_size (range->trough, &trough_width, &trough_height);
@@ -618,7 +660,7 @@ gtk_range_default_hmotion (GtkRange *range,
 
   new_pos = slider_x + xdelta;
 
-  if (range->flippable && gtk_widget_get_direction (GTK_WIDGET (range)) == GTK_TEXT_DIR_RTL)
+  if (should_invert (range, TRUE))
     new_pos = (right - new_pos) + left;
 
   if (new_pos < left)
@@ -686,6 +728,9 @@ gtk_range_default_vmotion (GtkRange *range,
 
   new_pos = slider_y + ydelta;
 
+  if (should_invert (range, FALSE))
+    new_pos = (bottom - new_pos) + top;
+  
   if (new_pos < top)
     new_pos = top;
   else if (new_pos > bottom)
index 3842ab44dc1eba3d23ccf3889adcf7ac07a5096d..5b48aeaedd4b36501e16d896f5b9b0eeec1140e2 100644 (file)
@@ -69,7 +69,8 @@ struct _GtkRange
   guint click_child : 3;
   guint need_timer : 1;
   guint flippable : 1;
-
+  guint inverted : 1;
+  
   guint32 timer;
 
   gfloat old_value;
@@ -123,8 +124,12 @@ void           gtk_range_set_update_policy      (GtkRange      *range,
 void           gtk_range_set_adjustment         (GtkRange      *range,
                                                 GtkAdjustment *adjustment);
 
+void           gtk_range_set_inverted           (GtkRange      *range,
+                                                 gboolean       setting);
+gboolean       gtk_range_get_inverted           (GtkRange      *range);
+
 void           gtk_range_draw_background        (GtkRange      *range);
-void           gtk_range_clear_background        (GtkRange      *range);
+void           gtk_range_clear_background       (GtkRange      *range);
 void           gtk_range_draw_trough            (GtkRange      *range);
 void           gtk_range_draw_slider            (GtkRange      *range);
 void           gtk_range_draw_step_forw         (GtkRange      *range);
index 5cf5f889a1e993201ff01937a629eb7294e6934b..205b0aac7c1b716e6322e3a646b750099217c536 100644 (file)
@@ -5238,7 +5238,7 @@ get_tree_bounds (GtkTextBTree *tree,
                  GtkTextIter *end)
 {
   _gtk_text_btree_get_iter_at_line_char (tree, start, 0, 0);
-  _gtk_text_btree_get_last_iter (tree, end);
+  _gtk_text_btree_get_end_iter (tree, end);
 }
 
 static void
index 65932b3dc014145e10ff7287edbe61b1dbe374be..17fd0a540b0bcc9f6f422546e957fa3b90f43eb9 100644 (file)
@@ -118,7 +118,7 @@ gboolean _gtk_text_btree_get_iter_at_mark_name    (GtkTextBTree       *tree,
 void     _gtk_text_btree_get_iter_at_mark         (GtkTextBTree       *tree,
                                                    GtkTextIter        *iter,
                                                    GtkTextMark        *mark);
-void     _gtk_text_btree_get_last_iter            (GtkTextBTree       *tree,
+void     _gtk_text_btree_get_end_iter             (GtkTextBTree       *tree,
                                                    GtkTextIter        *iter);
 void     _gtk_text_btree_get_iter_at_line         (GtkTextBTree       *tree,
                                                    GtkTextIter        *iter,
index 1a4ccdb1f097b1d2cae4f0951eaeabc1464efd40..6b09e25257f9256380203c06e0fe1ae33adf16ec 100644 (file)
@@ -1811,7 +1811,7 @@ gtk_text_buffer_place_cursor (GtkTextBuffer     *buffer,
 
   real = *where;
 
-  if (gtk_text_iter_is_last (&real))
+  if (gtk_text_iter_is_end (&real))
     gtk_text_iter_backward_char (&real);
 
   _gtk_text_btree_place_cursor (get_btree (buffer), &real);
@@ -2130,7 +2130,7 @@ gtk_text_buffer_get_iter_at_offset         (GtkTextBuffer      *buffer,
 }
 
 /**
- * gtk_text_buffer_get_last_iter:
+ * gtk_text_buffer_get_end_iter:
  * @buffer: a #GtkTextBuffer 
  * @iter: iterator to initialize
  *
@@ -2143,13 +2143,13 @@ gtk_text_buffer_get_iter_at_offset         (GtkTextBuffer      *buffer,
  * 
  **/
 void
-gtk_text_buffer_get_last_iter         (GtkTextBuffer      *buffer,
+gtk_text_buffer_get_end_iter         (GtkTextBuffer      *buffer,
                                        GtkTextIter        *iter)
 {
   g_return_if_fail (iter != NULL);
   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
 
-  _gtk_text_btree_get_last_iter (get_btree (buffer), iter);
+  _gtk_text_btree_get_end_iter (get_btree (buffer), iter);
 }
 
 /**
@@ -2172,7 +2172,7 @@ gtk_text_buffer_get_bounds (GtkTextBuffer *buffer,
   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
 
   _gtk_text_btree_get_iter_at_char (get_btree (buffer), start, 0);
-  _gtk_text_btree_get_last_iter (get_btree (buffer), end);
+  _gtk_text_btree_get_end_iter (get_btree (buffer), end);
 }
 
 /*
@@ -3078,7 +3078,7 @@ _gtk_text_buffer_get_line_log_attrs (GtkTextBuffer     *buffer,
   
   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
   g_return_val_if_fail (anywhere_in_line != NULL, NULL);
-  g_return_val_if_fail (!gtk_text_iter_is_last (anywhere_in_line), NULL);
+  g_return_val_if_fail (!gtk_text_iter_is_end (anywhere_in_line), NULL);
 
   /* FIXME we also need to recompute log attrs if the language tag at
    * the start of a paragraph changes
index 88bf91190b734e12d47e6d6765bf67abd51fd885..af00330cf72480b276e94f0648449f1eca2c97dd 100644 (file)
@@ -291,7 +291,7 @@ void gtk_text_buffer_get_iter_at_offset      (GtkTextBuffer *buffer,
 void gtk_text_buffer_get_iter_at_line        (GtkTextBuffer *buffer,
                                               GtkTextIter   *iter,
                                               gint           line_number);
-void gtk_text_buffer_get_last_iter           (GtkTextBuffer *buffer,
+void gtk_text_buffer_get_end_iter            (GtkTextBuffer *buffer,
                                               GtkTextIter   *iter);
 void gtk_text_buffer_get_bounds              (GtkTextBuffer *buffer,
                                               GtkTextIter   *start,
index c216d4ca3c9c2973a2ccbfb2e3272485914bcf4b..73a51ed368949fc164d847126b90fc3bdb271fa9 100644 (file)
@@ -730,7 +730,7 @@ gtk_text_iter_get_char (const GtkTextIter *iter)
 
   check_invariants (iter);
 
-  if (gtk_text_iter_is_last (iter))
+  if (gtk_text_iter_is_end (iter))
     return 0;
   else if (real->segment->type == &gtk_text_char_type)
     {
@@ -1382,18 +1382,18 @@ gtk_text_iter_ends_line (const GtkTextIter   *iter)
 }
 
 /**
- * gtk_text_iter_is_last:
+ * gtk_text_iter_is_end:
  * @iter: an iterator
  *
  * Returns TRUE if @iter is the end iterator, i.e. one past the last
- * dereferenceable iterator in the buffer. gtk_text_iter_is_last () is
+ * dereferenceable iterator in the buffer. gtk_text_iter_is_end () is
  * the most efficient way to check whether an iterator is the end
  * iterator.
  *
  * Return value: whether @iter is the end iterator
  **/
 gboolean
-gtk_text_iter_is_last (const GtkTextIter *iter)
+gtk_text_iter_is_end (const GtkTextIter *iter)
 {
   GtkTextRealIter *real;
 
@@ -1722,7 +1722,7 @@ forward_char (GtkTextRealIter *real)
 
       check_invariants ((GtkTextIter*)real);
 
-      if (gtk_text_iter_is_last ((GtkTextIter*)real))
+      if (gtk_text_iter_is_end ((GtkTextIter*)real))
         return FALSE;
       else
         return TRUE;
@@ -1813,7 +1813,7 @@ _gtk_text_iter_forward_indexable_segment (GtkTextIter *iter)
 
           check_invariants (iter);
 
-          if (gtk_text_iter_is_last (iter))
+          if (gtk_text_iter_is_end (iter))
             return FALSE;
           else
             return TRUE;
@@ -2111,7 +2111,7 @@ gtk_text_iter_forward_chars (GtkTextIter *iter, gint count)
       /* Return FALSE if we're on the non-dereferenceable end
        * iterator.
        */
-      if (gtk_text_iter_is_last (iter))
+      if (gtk_text_iter_is_end (iter))
         return FALSE;
       else
         return TRUE;
@@ -2303,7 +2303,7 @@ gtk_text_iter_forward_line (GtkTextIter *iter)
 
       check_invariants (iter);
 
-      if (gtk_text_iter_is_last (iter))
+      if (gtk_text_iter_is_end (iter))
         return FALSE;
       else
         return TRUE;
@@ -2415,7 +2415,7 @@ gtk_text_iter_forward_lines (GtkTextIter *iter, gint count)
       /* return whether it moved, and is dereferenceable. */
       return
         (gtk_text_iter_get_line (iter) != old_line) &&
-        !gtk_text_iter_is_last (iter);
+        !gtk_text_iter_is_end (iter);
     }
 }
 
@@ -2702,7 +2702,7 @@ find_by_log_attrs (GtkTextIter    *iter,
 
       return
         !gtk_text_iter_equal (iter, &orig) &&
-        !gtk_text_iter_is_last (iter);
+        !gtk_text_iter_is_end (iter);
     }
 }
 
@@ -3379,7 +3379,7 @@ gtk_text_iter_forward_to_end  (GtkTextIter *iter)
 
   buffer = _gtk_text_btree_get_buffer (real->tree);
 
-  gtk_text_buffer_get_last_iter (buffer, iter);
+  gtk_text_buffer_get_end_iter (buffer, iter);
 }
 
 /**
@@ -3477,7 +3477,7 @@ gtk_text_iter_forward_to_tag_toggle (GtkTextIter *iter,
           if (next_line == NULL)
             {
               /* End of search. Set to end of buffer. */
-              _gtk_text_btree_get_last_iter (real->tree, iter);
+              _gtk_text_btree_get_end_iter (real->tree, iter);
               return FALSE;
             }
 
@@ -4622,7 +4622,7 @@ _gtk_text_btree_get_iter_at_first_toggle (GtkTextBTree   *tree,
   if (line == NULL)
     {
       /* Set iter to last in tree */
-      _gtk_text_btree_get_last_iter (tree, iter);
+      _gtk_text_btree_get_end_iter (tree, iter);
       check_invariants (iter);
       return FALSE;
     }
@@ -4724,7 +4724,7 @@ _gtk_text_btree_get_iter_at_child_anchor (GtkTextBTree       *tree,
 }
 
 void
-_gtk_text_btree_get_last_iter         (GtkTextBTree   *tree,
+_gtk_text_btree_get_end_iter         (GtkTextBTree   *tree,
                                       GtkTextIter    *iter)
 {
   g_return_if_fail (iter != NULL);
index 2522588a7ad858f3e25199101deb96b0e0cda7a2..9b25a8be49419179edaaa1f97493dbec69aa3b86 100644 (file)
@@ -141,7 +141,7 @@ gint     gtk_text_iter_get_bytes_in_line (const GtkTextIter   *iter);
 gboolean gtk_text_iter_get_attributes    (const GtkTextIter    *iter,
                                           GtkTextAttributes    *values);
 gchar*   gtk_text_iter_get_language      (const GtkTextIter    *iter);
-gboolean gtk_text_iter_is_last           (const GtkTextIter    *iter);
+gboolean gtk_text_iter_is_end            (const GtkTextIter    *iter);
 gboolean gtk_text_iter_is_first          (const GtkTextIter    *iter);
 
 /*
index f220646b669db80a21c90f6fb78d0dc139c1c482..8cf21002a6c3f9d2521d0827cf366c47ef4bf938 100644 (file)
@@ -2487,7 +2487,7 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
 
   return
     !gtk_text_iter_equal (iter, &orig) &&
-    !gtk_text_iter_is_last (iter);
+    !gtk_text_iter_is_end (iter);
 }
 
 /**
@@ -2557,7 +2557,7 @@ gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
 
   return
     !gtk_text_iter_equal (iter, &orig) &&
-    !gtk_text_iter_is_last (iter);
+    !gtk_text_iter_is_end (iter);
 }
 
 /**
@@ -2617,7 +2617,7 @@ gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout,
 
   return
     !gtk_text_iter_equal (iter, &orig) &&
-    !gtk_text_iter_is_last (iter);
+    !gtk_text_iter_is_end (iter);
 }
 
 
@@ -2850,7 +2850,7 @@ gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
   
   return
     !gtk_text_iter_equal (iter, &orig) &&
-    !gtk_text_iter_is_last (iter);
+    !gtk_text_iter_is_end (iter);
 }
 
 void
index df233806b800744a74267b5607beaa9218c2143e..283a72e8b9ea4049bd4e48b52c59178d6d63bbc3 100644 (file)
@@ -3614,7 +3614,7 @@ gtk_text_view_move_cursor (GtkTextView     *text_view,
 
     case GTK_MOVEMENT_BUFFER_ENDS:
       if (count > 0)
-        gtk_text_buffer_get_last_iter (get_buffer (text_view), &newplace);
+        gtk_text_buffer_get_end_iter (get_buffer (text_view), &newplace);
       else if (count < 0)
         gtk_text_buffer_get_iter_at_offset (get_buffer (text_view), &newplace, 0);
       break;
index f257346ac940acdb642afdd0a7d30dcbbc215ac9..97bf5e270d26836f0f4d5c870e05f39068a41658 100644 (file)
@@ -2004,6 +2004,59 @@ create_sensitivity_control (GtkWidget *widget)
   return button;
 }
 
+static void
+set_selectable_recursive (GtkWidget *widget,
+                          gboolean   setting)
+{
+  if (GTK_IS_CONTAINER (widget))
+    {
+      GList *children;
+      GList *tmp;
+      
+      children = gtk_container_children (GTK_CONTAINER (widget));
+      tmp = children;
+      while (tmp)
+        {
+          set_selectable_recursive (tmp->data, setting);
+
+          tmp = tmp->next;
+        }
+      g_list_free (children);
+    }
+  else if (GTK_IS_LABEL (widget))
+    {
+      gtk_label_set_selectable (GTK_LABEL (widget), setting);
+    }
+}
+
+static void
+selectable_toggled (GtkWidget *toggle,
+                    GtkWidget *widget)
+{
+  set_selectable_recursive (widget,
+                            GTK_TOGGLE_BUTTON (toggle)->active);
+}
+
+static GtkWidget*
+create_selectable_control (GtkWidget *widget)
+{
+  GtkWidget *button;
+
+  button = gtk_toggle_button_new_with_label ("Selectable");  
+
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+                                FALSE);
+  
+  gtk_signal_connect (GTK_OBJECT (button),
+                      "toggled",
+                      GTK_SIGNAL_FUNC (selectable_toggled),
+                      widget);
+  
+  gtk_widget_show_all (button);
+
+  return button;
+}
+
 void create_labels (void)
 {
   static GtkWidget *window = NULL;
@@ -2033,6 +2086,10 @@ void create_labels (void)
 
       button = create_sensitivity_control (hbox);
 
+      gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+      button = create_selectable_control (hbox);
+
       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
       
       vbox = gtk_vbox_new (FALSE, 5);
@@ -6201,6 +6258,7 @@ create_range_controls (void)
   GtkWidget *scale;
   GtkWidget *separator;
   GtkObject *adjustment;
+  GtkWidget *hbox;
 
   if (!window)
     {
@@ -6241,6 +6299,25 @@ create_range_controls (void)
       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
       gtk_widget_show (scrollbar);
 
+      hbox = gtk_hbox_new (FALSE, 0);
+
+      scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
+      gtk_widget_set_usize (scale, -1, 200);
+      gtk_scale_set_digits (GTK_SCALE (scale), 2);
+      gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
+      gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
+      gtk_widget_show (scale);
+
+      scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
+      gtk_widget_set_usize (scale, -1, 200);
+      gtk_scale_set_digits (GTK_SCALE (scale), 2);
+      gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
+      gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
+      gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
+      gtk_widget_show (scale);
+      
+      gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
+      gtk_widget_show (hbox);
 
       separator = gtk_hseparator_new ();
       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
index 85c662ef0e317c810b124bbf09aee509acc336ae..292681e2befca4b73f3ee10d74467bad2d679d9b 100644 (file)
@@ -665,7 +665,7 @@ fill_file_buffer (GtkTextBuffer *buffer, const char *filename)
   /* We had a newline in the buffer to begin with. (The buffer always contains
    * a newline, so we delete to the end of the buffer to clean up.
    */
-  gtk_text_buffer_get_last_iter (buffer, &end);
+  gtk_text_buffer_get_end_iter (buffer, &end);
   gtk_text_buffer_delete (buffer, &iter, &end);
   
   gtk_text_buffer_set_modified (buffer, FALSE);
@@ -1281,7 +1281,7 @@ save_buffer (Buffer *buffer)
   else
     {
       gtk_text_buffer_get_iter_at_offset (buffer->buffer, &start, 0);
-      gtk_text_buffer_get_last_iter (buffer->buffer, &end);
+      gtk_text_buffer_get_end_iter (buffer->buffer, &end);
   
       chars = gtk_text_buffer_get_slice (buffer->buffer, &start, &end, FALSE);
 
@@ -1972,7 +1972,7 @@ get_lines (GtkTextView  *text_view,
   count = 0;
   size = 0;
 
-  while (!gtk_text_iter_is_last (&iter))
+  while (!gtk_text_iter_is_end (&iter))
     {
       gint y, height;
       gint line_num;
index b14ce64eef0713073c2f5ff7b675f4c33a6bad78..0d42dcb19a00a0fa892b0d6642f4bc674b9d9163 100644 (file)
@@ -186,7 +186,7 @@ check_specific_tag (GtkTextBuffer *buffer,
   state = FALSE;
   count = 0;
   
-  gtk_text_buffer_get_last_iter (buffer, &iter);
+  gtk_text_buffer_get_end_iter (buffer, &iter);
   last_offset = gtk_text_iter_get_offset (&iter);
   if (gtk_text_iter_toggles_tag (&iter, tag) ||
       gtk_text_iter_backward_to_tag_toggle (&iter, tag))
@@ -292,7 +292,7 @@ run_tests (GtkTextBuffer *buffer)
           g_error ("Mark not created in the right place.");
         }
 
-      if (gtk_text_iter_is_last (&iter))
+      if (gtk_text_iter_is_end (&iter))
         g_error ("iterators ran out before chars (offset %d of %d)",
                  i, num_chars);
 
@@ -474,7 +474,7 @@ run_tests (GtkTextBuffer *buffer)
   tag_states = g_hash_table_new (NULL, NULL);
   count = 0;
   
-  gtk_text_buffer_get_last_iter (buffer, &iter);
+  gtk_text_buffer_get_end_iter (buffer, &iter);
   if (gtk_text_iter_toggles_tag (&iter, NULL) ||
       gtk_text_iter_backward_to_tag_toggle (&iter, NULL))
     {
@@ -715,7 +715,7 @@ fill_buffer (GtkTextBuffer *buffer)
   gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);  
   
   tag = gtk_text_buffer_create_tag (buffer, "end_tag");
-  gtk_text_buffer_get_last_iter (buffer, &iter2);
+  gtk_text_buffer_get_end_iter (buffer, &iter2);
   gtk_text_iter_backward_chars (&iter2, 12);
   iter = iter2;
   gtk_text_iter_backward_chars (&iter, 157);
index f257346ac940acdb642afdd0a7d30dcbbc215ac9..97bf5e270d26836f0f4d5c870e05f39068a41658 100644 (file)
@@ -2004,6 +2004,59 @@ create_sensitivity_control (GtkWidget *widget)
   return button;
 }
 
+static void
+set_selectable_recursive (GtkWidget *widget,
+                          gboolean   setting)
+{
+  if (GTK_IS_CONTAINER (widget))
+    {
+      GList *children;
+      GList *tmp;
+      
+      children = gtk_container_children (GTK_CONTAINER (widget));
+      tmp = children;
+      while (tmp)
+        {
+          set_selectable_recursive (tmp->data, setting);
+
+          tmp = tmp->next;
+        }
+      g_list_free (children);
+    }
+  else if (GTK_IS_LABEL (widget))
+    {
+      gtk_label_set_selectable (GTK_LABEL (widget), setting);
+    }
+}
+
+static void
+selectable_toggled (GtkWidget *toggle,
+                    GtkWidget *widget)
+{
+  set_selectable_recursive (widget,
+                            GTK_TOGGLE_BUTTON (toggle)->active);
+}
+
+static GtkWidget*
+create_selectable_control (GtkWidget *widget)
+{
+  GtkWidget *button;
+
+  button = gtk_toggle_button_new_with_label ("Selectable");  
+
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+                                FALSE);
+  
+  gtk_signal_connect (GTK_OBJECT (button),
+                      "toggled",
+                      GTK_SIGNAL_FUNC (selectable_toggled),
+                      widget);
+  
+  gtk_widget_show_all (button);
+
+  return button;
+}
+
 void create_labels (void)
 {
   static GtkWidget *window = NULL;
@@ -2033,6 +2086,10 @@ void create_labels (void)
 
       button = create_sensitivity_control (hbox);
 
+      gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+      button = create_selectable_control (hbox);
+
       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
       
       vbox = gtk_vbox_new (FALSE, 5);
@@ -6201,6 +6258,7 @@ create_range_controls (void)
   GtkWidget *scale;
   GtkWidget *separator;
   GtkObject *adjustment;
+  GtkWidget *hbox;
 
   if (!window)
     {
@@ -6241,6 +6299,25 @@ create_range_controls (void)
       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
       gtk_widget_show (scrollbar);
 
+      hbox = gtk_hbox_new (FALSE, 0);
+
+      scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
+      gtk_widget_set_usize (scale, -1, 200);
+      gtk_scale_set_digits (GTK_SCALE (scale), 2);
+      gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
+      gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
+      gtk_widget_show (scale);
+
+      scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
+      gtk_widget_set_usize (scale, -1, 200);
+      gtk_scale_set_digits (GTK_SCALE (scale), 2);
+      gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
+      gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
+      gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
+      gtk_widget_show (scale);
+      
+      gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
+      gtk_widget_show (hbox);
 
       separator = gtk_hseparator_new ();
       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
index 85c662ef0e317c810b124bbf09aee509acc336ae..292681e2befca4b73f3ee10d74467bad2d679d9b 100644 (file)
@@ -665,7 +665,7 @@ fill_file_buffer (GtkTextBuffer *buffer, const char *filename)
   /* We had a newline in the buffer to begin with. (The buffer always contains
    * a newline, so we delete to the end of the buffer to clean up.
    */
-  gtk_text_buffer_get_last_iter (buffer, &end);
+  gtk_text_buffer_get_end_iter (buffer, &end);
   gtk_text_buffer_delete (buffer, &iter, &end);
   
   gtk_text_buffer_set_modified (buffer, FALSE);
@@ -1281,7 +1281,7 @@ save_buffer (Buffer *buffer)
   else
     {
       gtk_text_buffer_get_iter_at_offset (buffer->buffer, &start, 0);
-      gtk_text_buffer_get_last_iter (buffer->buffer, &end);
+      gtk_text_buffer_get_end_iter (buffer->buffer, &end);
   
       chars = gtk_text_buffer_get_slice (buffer->buffer, &start, &end, FALSE);
 
@@ -1972,7 +1972,7 @@ get_lines (GtkTextView  *text_view,
   count = 0;
   size = 0;
 
-  while (!gtk_text_iter_is_last (&iter))
+  while (!gtk_text_iter_is_end (&iter))
     {
       gint y, height;
       gint line_num;
index b14ce64eef0713073c2f5ff7b675f4c33a6bad78..0d42dcb19a00a0fa892b0d6642f4bc674b9d9163 100644 (file)
@@ -186,7 +186,7 @@ check_specific_tag (GtkTextBuffer *buffer,
   state = FALSE;
   count = 0;
   
-  gtk_text_buffer_get_last_iter (buffer, &iter);
+  gtk_text_buffer_get_end_iter (buffer, &iter);
   last_offset = gtk_text_iter_get_offset (&iter);
   if (gtk_text_iter_toggles_tag (&iter, tag) ||
       gtk_text_iter_backward_to_tag_toggle (&iter, tag))
@@ -292,7 +292,7 @@ run_tests (GtkTextBuffer *buffer)
           g_error ("Mark not created in the right place.");
         }
 
-      if (gtk_text_iter_is_last (&iter))
+      if (gtk_text_iter_is_end (&iter))
         g_error ("iterators ran out before chars (offset %d of %d)",
                  i, num_chars);
 
@@ -474,7 +474,7 @@ run_tests (GtkTextBuffer *buffer)
   tag_states = g_hash_table_new (NULL, NULL);
   count = 0;
   
-  gtk_text_buffer_get_last_iter (buffer, &iter);
+  gtk_text_buffer_get_end_iter (buffer, &iter);
   if (gtk_text_iter_toggles_tag (&iter, NULL) ||
       gtk_text_iter_backward_to_tag_toggle (&iter, NULL))
     {
@@ -715,7 +715,7 @@ fill_buffer (GtkTextBuffer *buffer)
   gtk_text_buffer_apply_tag (buffer, tag, &iter, &iter2);  
   
   tag = gtk_text_buffer_create_tag (buffer, "end_tag");
-  gtk_text_buffer_get_last_iter (buffer, &iter2);
+  gtk_text_buffer_get_end_iter (buffer, &iter2);
   gtk_text_iter_backward_chars (&iter2, 12);
   iter = iter2;
   gtk_text_iter_backward_chars (&iter, 157);